using System;
using System.Linq;
using FireStarterModeller.BO;
using FireStarterModeller.Logic;
using FireStarterModeller.Logic.Wizards;
using FireStarterModeller.Test.BO;
using FireStarterModeller.Test.BO.Fakes;
using NUnit.Framework;
using Rhino.Mocks;

namespace FireStarterModeller.Test.Logic
{
    [TestFixture]
    public class TestDMSolutionDeleter
    {
        #region Setup/Teardown

        [SetUp]
        public virtual void SetupTest()
        {
            TestUtilsLogic.SetupTest();
        }

        [TearDown]
        public virtual void TearDownTest()
        {
        }

        #endregion

        [TestFixtureSetUp]
        public virtual void TestFixtureSetup()
        {
            TestUtilsLogic.SetupFixture();
        }

        [Test]
        public void Test_Construct_WhenDMSolutionNull_ShouldRaiseError()
        {
            //---------------Set up test pack-------------------
            //---------------Assert Precondition----------------
            //---------------Execute Test ----------------------
            try
            {
                new DMSolutionDeleter(null);
                Assert.Fail("expected ArgumentNullException");
            }
                //---------------Test Result -----------------------
            catch (ArgumentNullException ex)
            {
                StringAssert.Contains("Value cannot be null", ex.Message);
                StringAssert.Contains("dmSolution", ex.ParamName);
            }
        }

        [Test]
        public void Test_Construct_ShouldSetDMSolution()
        {
            //---------------Set up test pack-------------------
            var mockDMSolution = MockRepository.GenerateStub<IDMSolution>();
            //---------------Assert Precondition----------------
            //---------------Execute Test ----------------------
            var dmSolutionDeleter = new DMSolutionDeleter(mockDMSolution);
            //---------------Test Result -----------------------
            Assert.AreSame(mockDMSolution, dmSolutionDeleter.DMSolution);
        }

        [Test]
        public void Test_Delete_WhenHasNoChildren_ShouldMarkForDelete()
        {
            //---------------Set up test pack-------------------
            var dmSolution = new DMSolution();
            var dmSolutionDeleter = new DMSolutionDeleter(dmSolution);
            //---------------Assert Precondition----------------
            Assert.AreEqual(0, dmSolution.Assemblies.Count);
            Assert.AreEqual(0, dmSolution.PropertyTypes.Count);
            Assert.IsFalse(dmSolution.Status.IsDeleted);
            //---------------Execute Test ----------------------
            dmSolutionDeleter.Delete();
            //---------------Test Result -----------------------
            Assert.IsTrue(dmSolution.Status.IsDeleted);
        }

        [Test]
        public void Test_Delete_WhenHasDMPropTypesThatAreSystem_ShouldMarkForDelete()
        {
            //If the Class is not involved in any Relationship and is not 
            // being used in Any Lookup Lists then it should be deleted.
            //---------------Set up test pack-------------------
            var dmSolution = new DMSolution();
            var dmSolutionDeleter = new DMSolutionDeleter(dmSolution);
            var propertyType = dmSolution.PropertyTypes.CreateBusinessObject();
            propertyType.AssemblyName = "System.CCC";
            //---------------Assert Precondition----------------
            Assert.IsEmpty(dmSolution.Assemblies);
            Assert.IsNotEmpty(dmSolution.PropertyTypes);
            string message;
            Assert.IsFalse(propertyType.IsDeletable(out message));
            //---------------Execute Test ----------------------
            dmSolutionDeleter.Delete();
            //---------------Test Result -----------------------
            Assert.IsTrue(dmSolution.Status.IsDeleted);
            Assert.IsTrue(propertyType.Status.IsDeleted);
            Assert.IsFalse(propertyType.ForceDelete);
        }

        [Test]
        public void Test_Delete_ShouldUseClassDeleter()
        {
            //If the Class is involved in any Relationship and is not 
            // being used in Any Lookup Lists then it should be deleted along with its Relationships.
            //---------------Set up test pack-------------------
            var dmSolution = new SolutionCreator().CreateSolution();

            var ucProp = TestUtilsDMUniqueConstraintProperty.CreateUnsavedValidDMUniqueConstraintProperty();
            var dmClass = ucProp.UniqueConstraint.Class;
            dmSolution.DefaultAssembly.Classes.Add(dmClass);
            var dmSolutionDeleter = new DMSolutionDeleter(dmSolution);
            //---------------Assert Precondition----------------
            Assert.IsNotNull(dmClass);
            Assert.IsNotNull(ucProp.Property);
            Assert.IsFalse(ucProp.Status.IsDeleted);
            Assert.IsFalse(ucProp.Property.Status.IsDeleted);
            Assert.IsFalse(ucProp.UniqueConstraint.Status.IsDeleted);
            //---------------Execute Test ----------------------
            dmSolutionDeleter.Delete();
            //---------------Test Result -----------------------
            Assert.IsTrue(ucProp.Status.IsDeleted);
            Assert.IsTrue(ucProp.Property.Status.IsDeleted);
            Assert.IsTrue(ucProp.UniqueConstraint.Status.IsDeleted);
            Assert.IsTrue(dmClass.Status.IsDeleted);
            Assert.IsTrue(dmSolution.Status.IsDeleted);
        }
    }
}